package glossos.tree.snapshot;

import glossos.tree.Node;
import glossos.tree.factory.NodeFactory;

import java.util.Arrays;

import org.apache.log4j.Logger;

public class InMemoryInsertionSnapshot implements InsertionSnapshot {
    private static Logger logger = Logger.getLogger("glossos.index");
    private Node[] nodes, temp, mostFrequent;
    private NodeFactory nodeFactory;
    private NodeRepository nodeRepository;

    public InMemoryInsertionSnapshot(int size, NodeFactory nodeFactory) {
        this.nodeFactory = nodeFactory;
        nodes = nodeFactory.createArray(size);
        temp = nodeFactory.createArray(size);
        mostFrequent = nodeFactory.createArray(size);
    }

    public void setNodeRepository(NodeRepository nodeRepository) {
        this.nodeRepository = nodeRepository;
    }

    public void insert(Node node) {
        nodes[0] = node;
        node.setId(1L);
        nodeRepository.save(node);
    }

    public Node atLevel(int level) {
        return nodes[level];
    }

    public Node root() {
        Node level0 = atLevel(0);
        return level0 != null
            ? level0
            : nodeRepository.findById(1L);
    }

    public void appendWordUnderLevel(String word, int level) {
        if (canAppendUnderLevel(level)) {
            temp[level] = nodes[level].append(nodeFactory.create(word));
            if (mostFrequent[level] == null || mostFrequent[level].lessFrequentThan(temp[level]))
                mostFrequent[level] = temp[level];
        }
    }

    public boolean canAppendUnderLevel(int level) {
        return level < nodes.length && nodes[level] != null;
    }

    public void commit() {
        System.arraycopy(temp, 0, nodes, 1, nodes.length - 1);
    }

    public Node mostFrequentAtLevel(int level) {
        return mostFrequent[level - 1];
    }

    @Override
    public String toString() {
        return Arrays.asList(nodes).toString();
    }

    public void reset() {
//		temp = nodeFactory.createArray(nodes.length);
        temp = new Node[nodes.length];
        Node root = root();
//		nodes = nodeFactory.createArray(nodes.length);
        nodes = new Node[nodes.length];
        nodes[0] = root;
    }

    public int height() {
        return nodes.length;
    }
}
